/***************************************************
> Copyright (C) 2024 ==KINGYI== All rights reserved.
> File Name: server.c
> Author:luohong
> Mail: 750232205@qq.com
> Created Time: 2024年09月20日 星期五 18时37分50秒
***************************************************/

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "threadpool.h"
#include "serverfun.h"

int sockfd;

//接收是数据存入队列
void *fun1(void *arg){
    struct exam1 *p = (struct exam1 *)arg;
    char dest[1024] = {0};//接收
    int ret = 0;
    struct msg msge;
    memset(&msge,0,sizeof(struct msg));
    int len = sizeof(struct sockaddr);
    while(1){
        memset(dest,0,sizeof(dest));
        ret = recvfrom(sockfd,dest,sizeof(dest),0,(struct sockaddr *)&msge.addr,&len);
        puts(dest);
        if(ret == -1){
            perror("recvfrom");
            exit(-1);
        }
        memcpy(msge.buf,dest,sizeof(dest));

        
        sem_wait(&p->semw);//p操作

        pthread_mutex_lock(&p->mutex);
        push(p->que,msge);
        pthread_mutex_unlock(&p->mutex);

        sem_post(&p->semr);//v操作
        sleep(1);
    }
    
}

//从队列中取出数据处理数据并返回
void *fun2(void *arg){
    struct thread_pool *p = (struct thread_pool *)arg;
    int ret = 0;
    struct task taskr;
    char recvType[10] = {0};
    memset(&taskr,0,sizeof(struct task));
    while(1){
    
        sem_wait(&p->semr);//p

        pthread_mutex_lock(&p->mutex);
        taskr = tfront(p->que);
        tpop(p->que);
        pthread_mutex_unlock(&p->mutex);
        
        cJSON *json = NULL;
		json = cJSON_Parse(taskr.buf);
        cJSON *node = NULL;
        node = cJSON_GetObjectItem(json,"type");
		if(node == NULL){
			printf("can't find type\n");
			exit(-1);
		}
        if(node->type == cJSON_String){
				strcpy(recvType,node->valuestring);
        }
        if(strcmp(recvType,"bind") == 0){
            //绑定设备
            printf("node1\n");
            bindEqu(taskr);
        }else if(strcmp(recvType,"unbind") == 0){
            //解绑设备
            unbingEqu(taskr);
        }else if(strcmp(recvType,"getuser") == 0){
            //获取用户信息
            getuserinfo(taskr);
        }else if(strcmp(recvType,"getrech") == 0){
            //获取充值记录
            getRechRecord(taskr);
        }else if(strcmp(recvType,"getoper") == 0){
            //获取远程控制记录
            getOperrecord(taskr);
        }
        sem_post(&p->semw);//v
        sleep(3);
    }
       
}

//接收是数据存入队列
void *fun3(void *arg){
    struct exam *p = (struct exam *)arg;
    char dest[100] = {0};//接收
    int ret = 0;
    struct info infor;
    memset(&infor,0,sizeof(struct info));
    int len = sizeof(struct sockaddr);
    while(1){
        memset(dest,0,sizeof(dest));
        ret = recvfrom(sockfd,dest,sizeof(dest),0,(struct sockaddr *)&infor.addr,&len);
        puts(dest);
        if(ret == -1){
            perror("recvfrom");
            exit(-1);
        }
        memcpy(infor.buf,dest,sizeof(dest));

        
        sem_wait(&p->semw);//p操作

        pthread_mutex_lock(&p->mutex);
        epush(p->que,infor);
        pthread_mutex_unlock(&p->mutex);

        sem_post(&p->semr);//v操作
        sleep(1);
    }
    
}

void *fun4(void *arg){
    struct exam *p = (struct exam *)arg;
    int ret = 0;
    struct info infor;
    char recvType[10] = {0};
    memset(&infor,0,sizeof(struct info));

    
    while(1){
    
        sem_wait(&p->semr);//p

        pthread_mutex_lock(&p->mutex);
        infor = efront(p->que);
        epop(p->que);
        pthread_mutex_unlock(&p->mutex);
        
        cJSON *json = NULL;
		json = cJSON_Parse(infor.buf);
        cJSON *node = NULL;
        node = cJSON_GetObjectItem(json,"type");
		if(node == NULL){
			printf("can't find type\n");
			exit(-1);
		}
        if(node->type == cJSON_String){
				strcpy(recvType,node->valuestring);
        }
        if(strcmp(recvType,"gather") == 0){
            //接收采集的数据处理
            recvfromEqu(infor);
        }else if(strcmp(recvType,"recharge") == 0){
            //充值
            _recharge(infor);
        }
        sem_post(&p->semw);//v
        sleep(3);
    }
       
}

int main(int argc,const char* argv[])
{

    initDB();
    int ret = 0;
    sockfd = socket(AF_INET,SOCK_DGRAM,0);
    if(sockfd == -1){
        perror("socket");
        exit(-1);
    }

    struct sockaddr_in addr;
    struct sockaddr_in cliaddr;

    struct exam ex;
    struct exam1 ex1;

    struct task taskr;
    char recvType[10] = {0};
    memset(&taskr,0,sizeof(struct task));

    struct msg msge;
    memset(&msge,0,sizeof(struct msg));

    ex.que = create_equeue();
    sem_init(&ex.semw,0,1);
    sem_init(&ex.semr,0,0);
    pthread_mutex_init(&ex.mutex,NULL);

    ex1.que = create_queue();
    sem_init(&ex1.semw,0,1);
    sem_init(&ex1.semr,0,0);
    pthread_mutex_init(&ex1.mutex,NULL);

    memset(&addr,0,sizeof(addr));
    memset(&cliaddr,0,sizeof(cliaddr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(6869);
    addr.sin_addr.s_addr = inet_addr("192.168.0.181");

    ret = bind(sockfd,(struct sockaddr *)&addr,sizeof(struct sockaddr));
    if(ret == -1){
        perror("bind");
        exit(-1);
    }

    pthread_t tid = 0;
    pthread_t tid3 = 0;
    pthread_t tid4 = 0;
    struct thread_pool *pool = create_threadpool(10,100,fun2);//从队列中取出数据处理数据并返回
    ret = pthread_create(&tid,NULL,fun1,&ex1);//接收是数据存入队列
    if(ret != 0){
        printf("pthread_create error\n");
        exit(-1);
    }

    ret = pthread_create(&tid3,NULL,fun3,&ex);//接收设备端采集的数据存入队列
    if(ret != 0){
        printf("pthread_create error\n");
        exit(-1);
    }

    ret = pthread_create(&tid4,NULL,fun4,&ex);//从队列中取出数据处理
    if(ret != 0){
        printf("pthread_create error\n");
        exit(-1);
    }




    while(1){
    
        sem_wait(&ex1.semr);//p

        pthread_mutex_lock(&ex1.mutex);
        msge = front(ex1.que);
        pop(ex1.que);
        pthread_mutex_unlock(&ex1.mutex);
        
        cJSON *json = NULL;
		json = cJSON_Parse(msge.buf);
        cJSON *node = NULL;
        node = cJSON_GetObjectItem(json,"type");
		if(node == NULL){
			printf("can't find type\n");
			exit(-1);
		}
        if(node->type == cJSON_String){
				strcpy(recvType,node->valuestring);
        }
        if(strcmp(recvType,"login") == 0){
            //登录
            login(msge);
        }
        else if(strcmp(recvType,"register") == 0){
            //注册
            uormregister(msge);
        }else{
            taskr.addr = msge.addr;
            strcpy(taskr.buf,msge.buf);
            sem_wait(&pool->semw);//p操作

            pthread_mutex_lock(&pool->mutex);
            tpush(pool->que,taskr);
            pthread_mutex_unlock(&pool->mutex);

            sem_post(&pool->semr);//v操作
            sleep(1);
        }
        sem_post(&ex1.semw);//v
    }



    pthread_join(tid,NULL);
    pthread_join(tid3,NULL);
    pthread_join(tid4,NULL);
    for(int i = 0;i < pool->threads;i++){
        pthread_join(pool->tids[i],NULL);
    }
    
    destroy_threadpool(pool);
    return 0;
}
